package com.metro.demo.web.filter.security;

import com.metro.demo.common.beans.vo.WebUserInfo;
import com.metro.demo.sys.beans.constant.SystemConstant;
import com.metro.demo.sys.beans.vo.SysPermission;
import com.metro.demo.sys.beans.vo.SysRole;
import com.metro.demo.sys.beans.vo.SysUser;
import com.metro.demo.sys.service.inf.ISysPermissionService;
import com.metro.demo.sys.service.inf.ISysRoleService;
import com.metro.demo.sys.service.inf.ISysUserService;
import com.metro.demo.web.filter.security.vo.BaseUsernamePasswordToken;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

public class SecurityRealm extends AuthorizingRealm {
	
	@Autowired
	private ISysUserService sysUserService;
	@Autowired
	private ISysRoleService sysRoleService;
	//权限
	@Autowired
	private ISysPermissionService sysPermissionService;

	// private final org.apache.commons.logging.Log log = Res.getLog(this.getClass());

	public SecurityRealm() {
		super();
		// 设置认证token的实现类
		setAuthenticationTokenClass(BaseUsernamePasswordToken.class);
		// 设置加密算法
		setCredentialsMatcher(new HashedCredentialsMatcher(Md5Hash.ALGORITHM_NAME)); //MD5加密
	}

	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		WebUserInfo userInfo = (WebUserInfo) principals.fromRealm(getName()).iterator().next(); 
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		//1.角色
		List<SysRole> roleEntityList = sysRoleService.queryRoleByUserId(userInfo.getUserId());
		userInfo.setRoleList(roleEntityList);
		info.addRoles(userInfo.getRoleCodeList());
		//2.权限
		String roleIds = userInfo.getRoleIds();
		if(StringUtils.isNotBlank(roleIds)){
			List<SysPermission> permissionList = sysPermissionService.queryMenuByRoleIds(roleIds);
			userInfo.setPermissionList(permissionList);
			List<String> permissions = userInfo.getPermissions();
			info.addStringPermissions(permissions);
		}
		return info;
	}

	/** * 更新用户授权信息缓存. */
	public void clearCachedAuthorizationInfo(String principal) {
		SimplePrincipalCollection principals = new SimplePrincipalCollection(principal, getName());
		clearCachedAuthorizationInfo(principals);
	}

	/**
	 * 清除所有用户授权信息缓存.
	 */
	public void clearAllCachedAuthorizationInfo() {
		Cache<Object, AuthorizationInfo> cache = getAuthorizationCache();
		if (cache != null) {
			for (Object key : cache.keys()) {
				cache.remove(key);
			}
		}
	}

	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authToken) throws AuthenticationException {
		BaseUsernamePasswordToken token = (BaseUsernamePasswordToken) authToken;
		SysUser user = sysUserService.getSysUserByAccount(token.getUsername());
		if (user != null) {
			if (SystemConstant.USER_LOCKED.equals(user.getStatus())) {
				throw new LockedAccountException("账号被锁定");
			}
			WebUserInfo currUserInfo = new WebUserInfo();
			currUserInfo.setUser(user);
			return new SimpleAuthenticationInfo(currUserInfo, user.getPassword(), getName());
		} else {
			throw new UnknownAccountException("账号密码错误");
		}
	}
}
